from fuzzywuzzy import fuzz
import heapq
import re


def deletekognge(a):
    b = []
    for i in a:
        j = i.replace(' ', '')
        jj = re.sub(u"\\(.*?\\)|\\{.*?}|\\[.*?]", "", j)
        b.append(jj)
        pass
    return b


#  ——————————全部转小写——————————

# def tolower(a):
#     b = []
#     list2 = [str(x) for x in a]
#     for i in list2:
#         i = i.lower()
#         b.append(i)
#     return b


# ________match score function__________ B is real name
# def fuzzy_match_strings(A, B):
#
#     similarity_values = []  # 用于记录相似度的数组
#     matched_strings = []  # 用于存储替换后的结果
#     progress = 0
#     total = len(A) * len(B)
#
#     Alower2 = tolower(A)  # 转小写
#     # Alower2 = deletekognge(Alower)  #删除括号的内容和空格
#     Blower = tolower(B)
#     # Blower = deletekognge(Blowe)
#
#     for a in Alower2:
#         max_similarity = 0
#
#         for j, b in enumerate(Blower):
#             similarity = fuzz.ratio(a, b)  # 使用Levenshtein距离计算相似度
#             if similarity > max_similarity:
#                 max_similarity = similarity
#                 index = j
#
#             # progress += 1
#             # if (progress % 1000 == 0):
#             #     print(f"Progress: {progress}/{total}")
#
#         # similarity_values.append(round(max_similarity / 100, 4))  # 将相似度转化为小数形式
#         # matched_strings.append(matched_string)
#         matched_strings.append(B[index])
#
#     print(matched_strings)
#     return matched_strings, similarity_values

def tolower(list_of_strings):
    return [s.lower() for s in list_of_strings]


# def fuzzy_match_strings(a, B):
#     # 转小写
#     a_lower = a.lower()
#     Blower = tolower(B)
#
#     # 创建一个最小堆来存储最高的20个相似度值和对应的字符串
#     heap = []
#
#     for b in Blower:
#         similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
#         # 将元素推入堆中，如果堆的大小超过20，则弹出最小的元素
#         if len(heap) < 20:
#             heapq.heappush(heap, (similarity, b))
#         else:
#             heapq.heappushpop(heap, (similarity, b))
#
#     # 获取相似度最高的20个元素并按相似度从高到低排序
#     top_matches = sorted(heap, key=lambda x: x[0], reverse=True)
#
#     # 只返回匹配的字符串，不包括相似度值
#     return [match for _, match in top_matches]

def fuzzy_match_strings(a, B):
    # 转小写

    a_lower = a.lower()
    B_lower = tolower(deletekognge(B))

    # 创建一个最小堆来存储最高的20个相似度值和对应的字符串
    heap = []

    for index, b in enumerate(B_lower):
        similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
        # 将元素推入堆中，如果堆的大小超过20，则弹出最小的元素
        if len(heap) < 50:
            heapq.heappush(heap, (similarity, index))
        else:
            heapq.heappushpop(heap, (similarity, index))

    # 获取相似度最高的20个元素并按相似度从高到低排序
    top_matches = sorted(heap, key=lambda x: x[0], reverse=True)

    # 根据索引在原数组B中找对应的值
    return [B[i] for _, i in top_matches]


# def fuzzy_match_strings2(a, B, degree=0.9):
#     # 转小写
#     a_lower = a.lower()
#     B_lower = tolower(deletekognge(B))
#
#     # 创建一个列表来存储所有相似度大于0.8的值
#     matches = []
#
#     for index, b in enumerate(B_lower):
#         similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
#         # 如果相似度大于degree，就将元素放入列表中
#         if similarity > degree:
#             matches.append((similarity, index))
#
#     # 根据相似度从高到低排序
#     matches = sorted(matches, key=lambda x: x[0], reverse=True)
#
#     # 根据索引在原数组B中找对应的值
#     return [B[i] for _, i in matches]

# 如果有大于0.95的，就返回那一个元素即可
def fuzzy_match_strings2(a, B, degree=0.8):
    a_lower = a.lower()
    B_lower = [b.lower() for b in B]

    matches = []

    for index, b in enumerate(B_lower):
        similarity = fuzz.ratio(a_lower, b)
        if similarity > degree:
            matches.append((similarity, index))

    matches = sorted(matches, key=lambda x: x[0], reverse=True)

    # 如果最大相似度大于0.95，只返回最相似的元素
    if matches and matches[0][0] > 0.95:
        return [B[matches[0][1]]]

    return [B[i] for _, i in matches]


# def fuzzy_match_strings3(a, B):
#     # 转小写
#
#     a_lower = a.lower()
#     B_lower = tolower(deletekognge(B))
#
#
#     heap = []
#
#     for index, b in enumerate(B_lower):
#         similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
#         heapq.heappush(heap, (similarity, index))
#
#     top_matches = sorted(heap, key=lambda x: x[0], reverse=True)
#
#     # 根据索引在原数组B中找对应的值
#     return [B[i] for _, i in top_matches]
def fuzzy_match_strings3(a, B):
    # 转小写
    a_lower = a.lower()
    B_lower = [b.lower() for b in B]

    heap = []

    for index, b in enumerate(B_lower):
        similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
        heapq.heappush(heap, (similarity, index))

    top_matches = sorted(heap, key=lambda x: x[0], reverse=True)

    # 根据索引在原数组B中找对应的值，并保留相似度用于排序
    return [(B[i], similarity) for similarity, i in top_matches]


def fuzzy_match_strings4(a, B):
    # 转小写
    a_lower = a.lower()
    B_lower = [b.lower() for b in B]

    heap = []

    for index, b in enumerate(B_lower):
        similarity = fuzz.ratio(a_lower, b)  # 使用Levenshtein距离计算相似度
        heapq.heappush(heap, (similarity, index))

    # top_matches = sorted(heap, key=lambda x: x[0], reverse=True)
    top_matches = heapq.nlargest(20, heap, key=lambda x: x[0])
    # 根据索引在原数组B中找对应的值，并保留相似度用于排序
    return [(B[i], similarity) for similarity, i in top_matches]


